﻿using System;
using System.Collections.Generic;
using System.IO;

namespace ExcelConfig
{
    using ExcelConfig.Config;
    using ExcelConfig.helpers;

    /// <summary>
    /// 只读
    /// </summary>
    public class ExcelFile
    {
        internal string path { get; set; }
        internal string current_sheet { get; set; }
        internal string current_field_key { get; set; }
        internal string current_field_value { get; set; }
        internal ExcelFile() { }
        public ExcelFile(string path)
        {
            this.path = path;
            this.ToSheet(ExcelConfigSetting.SHEET_Global);
            this.SetKeyField(ExcelConfigSetting.COLUMN_KEY);
            this.SetValueField(ExcelConfigSetting.COLUMN_VALUE);
        }
        public static ExcelFile Load(string path, string sheet)
        {
            var excel = new ExcelFile();
            excel.path = path;
            excel.current_sheet = sheet;
            return excel;
        }
        public string FullPath { get { return path; } }
        public string SheetName { get { return current_sheet; } }
        public string Key { get { return current_field_key; } }
        /// <summary>
        /// 转到指定Sheet
        /// </summary>
        /// <param name="sheetname"></param>
        public void ToSheet(string sheetname)
        {
            this.current_sheet= sheetname;

        }
        /// <summary>
        /// 设置 取键列
        /// </summary>
        public void SetKeyField(string fieldName)
        {
            this.current_field_key = fieldName;
        }
        /// <summary>
        /// 设置 取值列
        /// </summary>
        public void SetValueField(string fieldName)
        {
            this.current_field_value = fieldName;
        }

        public string Text(string name)
        {
            var line = ReadConfig(current_sheet, name);
            return line.Text(current_field_value);
        }
        public decimal Number(string name)
        {
            var line = ReadConfig(current_sheet, name);
            return line.Number(current_field_value);
        }
        public bool YesOrNo(string name)
        {
            var line = ReadConfig(current_sheet, name);
            return line.YesOrNo(current_field_value);
        }
        public string[] Array(string name)
        {
            var line = ReadConfig(current_sheet, name);
            return line.Array(current_field_value);
        }
        public SheetLine ReadLine(string key)
        {
            return ReadConfig(current_sheet, key);
        }
        public bool ContainSheets(string sheetname)
        {
            if (File.Exists(path))
                foreach (var name in MiniExcel.GetSheetNames_enum(path))
                    if (name.Equals(sheetname)) return true;

            return false;
        }
        public IEnumerable<string> LoopSheetNames()
        {
            return MiniExcel.GetSheetNames_enum(path);
        }
        internal SheetLine ReadConfig(string sheetname, string key)
        {
            this.current_sheet = sheetname;
            this.current_field_key = key;
            if (!File.Exists(path)) goto ERROR;
            var sheets = MiniExcel.GetSheetNames(path);
            if (!sheets.Contains(sheetname)) goto ERROR;

            var sheet = MiniExcel.Query(path, true, sheetname);
            foreach(var sheet_item in sheet)
                foreach (var sheet_item_prop in sheet_item)
                    if (sheet_item_prop.Key!= null &&sheet_item_prop.Key == this.current_field_key && helper.parse_to_text(sheet_item_prop.Value).Equals(key))
                        return new SheetLine(sheet_item);
        ERROR:
            return default;
        }
        public CellObj Read(string colname)
        {
            foreach (var item in MiniExcel.Query(path, false, this.SheetName, startCell: colname))
                foreach (var cell in item) return new CellObj(cell.Value);
            return new CellObj(null);
        }
        public CellObj Read(int rowno, int colno)
        {
            if (rowno <= 0 || colno <= 0) throw new ArgumentException("param lt 0");
            return Read(helper.calc_excel_cellname(rowno - 1, colno - 1));
        }
        public IEnumerable<SheetLine> ReadAllLine()
        {
            return ReadAllLine(current_sheet);
        }
        internal IEnumerable<SheetLine> ReadAllLine(string sheetname, bool ignore_empty=true)
        {
            this.current_sheet = sheetname;
            if (!File.Exists(path)) goto ERROR;
            var sheets = MiniExcel.GetSheetNames(path);
            if (!sheets.Contains(sheetname)) goto ERROR;

            foreach (var _sheet_item in MiniExcel.Query(path, true, sheetname))
            {
                var not_null = false;
                foreach (var cell in _sheet_item) if (not_null = cell.Value != null) break;
                if (!not_null) continue;

                if (!ignore_empty) yield return new SheetLine(_sheet_item);
                else
                {
                    foreach (var cell in _sheet_item)
                    {
                        if (cell.Value == null) continue;
                        if (this.current_field_key == null || cell.Key == this.current_field_key)
                        {
                            yield return new SheetLine(_sheet_item);
                            break;
                        }
                    }
                }
            }
        ERROR:;
        }
    }
}
